package edu.pitt.myptm.scheduler;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;

import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;

import edu.pitt.myptm.MyCommand;

public class LockManager {

	public int IdentifyCmdType(MyCommand cmd,Hashtable<Integer,Integer> TranTable,Hashtable<Integer,Integer> ProcessTable){
		System.out.println("TranTable size="+TranTable.size()+ " ProcessTable size="+ProcessTable.size());
		if(TranTable.get(cmd.getTransactionId())!=null){
			if(cmd.isReadCommand())
				return 0;
			else if(cmd.isWriteCommand())
				return 1;
			else if(cmd.isMatchCommand())
				return 2;
			else
				return 3;
		} else {
			if(cmd.isReadCommand())
				return 4;
			else if(cmd.isWriteCommand())
				return 5;
			else if(cmd.isMatchCommand())
				return 6;
			else
				return 7;
		}
	}
	
	public int IdentifyOptType(OperationTuple OT,Hashtable<Integer,Integer> TranTable,Hashtable<Integer,Integer> ProcessTable){
		if(TranTable.get(OT.tranID)!=null){
			return OT.operation;
		} else {
			return OT.operation+4;
		}
	}
	
	public void insert_lock_table_holder(LockContent LC,MyCommand cmd){
		OperationTuple OT= new OperationTuple();
		OT.tranID=cmd.getTransactionId();
		if(cmd.isReadCommand())
			OT.operation=MyCommand.READ;
		else if(cmd.isWriteCommand())
			OT.operation=MyCommand.WRITE;
		else if(cmd.isDeleteCommand())
			OT.operation=MyCommand.DELETE;
		else if(cmd.isMatchCommand())
			OT.operation=MyCommand.MATCH;
		
		if(LC.lock_holder==null)
			LC.lock_holder=new ArrayList<OperationTuple>();
		
		LC.lock_holder.add(OT);
	}
	
	public boolean insert_lock_table_waiter(LockContent LC,MyCommand cmd){
		
		if(LC.waiting_list==null)
			LC.waiting_list=new ArrayList<MyCommand>();
		
		//check duplicate
		for(int i=0; i<LC.waiting_list.size();i++){
			if(cmd.isDeleteCommand()||cmd.isMatchCommand()){
				if(LC.waiting_list.get(i).getFilename().equals(cmd.getFilename())
						&&LC.waiting_list.get(i).getType()==cmd.getType()
						&&LC.waiting_list.get(i).getTimeStamp()==cmd.getTimeStamp())
						return false;
			} else {
				if(LC.waiting_list.get(i).getFilename().equals(cmd.getFilename())
					&&LC.waiting_list.get(i).getId()==cmd.getId()
					&&LC.waiting_list.get(i).getType()==cmd.getType()
					&&LC.waiting_list.get(i).getTimeStamp()==cmd.getTimeStamp())
						return false;
			}
		}
		
		LC.waiting_list.add(cmd);
/*		LC.waiting_list.add(cmd.getTransactionId());
		if(cmd.isReadCommand())
			LC.waiting_list_type.add("read");
		else if(cmd.isWriteCommand())
			LC.waiting_list_type.add("write");*/
		return true;
	}
	
	public void WFGInsertEdge(DefaultDirectedGraph<Integer, DefaultEdge> WFG, MyCommand cmd,LockContent LC){
		WFG.addVertex(cmd.getTransactionId());
		if(LC!=null){
			if(LC.lock_holder!=null){
				for(int j=0; j<LC.lock_holder.size();j++){
					WFG.addVertex(LC.lock_holder.get(j).tranID);
					WFG.addEdge(cmd.getTransactionId(),LC.lock_holder.get(j).tranID);
				}
			}
		}
	}
	
	public void WFGDeleteEdge(DefaultDirectedGraph<Integer, DefaultEdge> WFG, MyCommand cmd){
		if(WFG.containsVertex(cmd.getTransactionId())){
			Set<DefaultEdge> EdgeSet=WFG.outgoingEdgesOf(cmd.getTransactionId());
			while(EdgeSet.iterator().hasNext()){
				DefaultEdge E=EdgeSet.iterator().next();
				WFG.removeEdge(E);
			}
		}
	}
	
	public boolean update_waiting_in_lock_holder_waiting_list(MyCommand cmd,Hashtable<LockTuple,LockContent> lock_table,
			Hashtable<Integer, LockGranted> lock_holder_waitting_list,LockTuple LT){
		LockGranted LG=lock_holder_waitting_list.get(cmd.getTransactionId());
		if(LG==null){
			LG=new LockGranted();
			if(LG._lock_waiting==null)
				LG._lock_waiting=new ArrayList<LockTuple>();
			LG._lock_waiting.add(LT);
			lock_holder_waitting_list.put(cmd.getTransactionId(),LG);
			System.out.println("++++++-+-+-+-+-+-+"+cmd.getFilename()
					+" "+cmd.getId()+" "+cmd.getType()
					+" "+cmd.getTimeStamp());
		} else{
			if(LG._lock_waiting==null)
				LG._lock_waiting=new ArrayList<LockTuple>();
			
			//check duplicate. if no duplicate, insert; otherwise no need to insert
/*			for(int i=0;i<LG._lock_waiting.size();i++){
				System.out.println("--000000000----"+LG._lock_waiting.get(i).file_name
						+" "+LG._lock_waiting.get(i).record_ID+" "+LG._lock_waiting.get(i).operationType);
				
				if(cmd.isReadCommand()){
					if((LG._lock_waiting.get(i).file_name.equals(cmd.getFilename()))
					 &&(LG._lock_waiting.get(i).record_ID==cmd.getId())
					 &&(LG._lock_waiting.get(i).operationType==cmd.getType()))
						
						System.out.println("no need to insert to waiting_in_lock_holder_waiting_list");
						return false;
				}
				if(cmd.isWriteCommand()){
					if((LG._lock_waiting.get(i).file_name.equals(cmd.getFilename()))
							 &&(LG._lock_waiting.get(i).record_ID==cmd.getDataItem().getId())
							 &&(LG._lock_waiting.get(i).operationType==cmd.getType()))
								
						System.out.println("no need to insert to waiting_in_lock_holder_waiting_list");
						return false;
				}
			}
	*/		
			LG._lock_waiting.add(LT);
			System.out.println("++++++-+-+-+-+-+-+"+cmd.getFilename()
					+" "+cmd.getId()+" "+cmd.getType()
					+" "+cmd.getTimeStamp());
		}
		return true;
	}
	
	public void update_grant_in_lock_holder_waiting_list(MyCommand cmd,Hashtable<LockTuple,LockContent> lock_table,
			Hashtable<Integer, LockGranted> lock_holder_waitting_list,LockTuple LT){
		LockGranted LG=lock_holder_waitting_list.get(cmd.getTransactionId());
		if(LG==null){
			LG=new LockGranted();
			if(LG._lock_granted==null)
				LG._lock_granted=new ArrayList<LockTuple>();
			LG._lock_granted.add(LT);
			lock_holder_waitting_list.put(cmd.getTransactionId(),LG);
		} else {
			if(LG._lock_granted==null)
				LG._lock_granted=new ArrayList<LockTuple>();
			LG._lock_granted.add(LT);
		}
	}
	
	public void print_lock_table(Hashtable<LockTuple,LockContent> lock_table){
		for(Enumeration<LockContent> e=lock_table.elements();e.hasMoreElements();){
			LockContent LC= e.nextElement();
			if(LC!=null){
				int size=LC.lock_holder.size();
				for(int j=0;j<size;j++){
					System.out.println(" "+LC.lock_holder.get(j).tranID+" "+LC.lock_holder.get(j).operation);
						
				}
			}
		}
	}
	
	public void print_lock_table_key(Hashtable<LockTuple,LockContent> lock_table){		
		for(Enumeration<LockTuple> e=lock_table.keys();e.hasMoreElements();){
			LockTuple LT= e.nextElement();
			if(LT!=null){
					System.out.println(" "+LT.file_name+" "+LT.record_ID);
			}
		}
	}
	
	public boolean check_lock_table(MyCommand cmd,Hashtable<LockTuple,LockContent> lock_table,
										Hashtable<Integer, LockGranted> lock_holder_waitting_list,
										CompatibleTable ComTable,boolean from_release,
										DefaultDirectedGraph<Integer, DefaultEdge> WFG, DeadLockManager DLM,
										Hashtable<String,LockContent> file_lock_table,
										Hashtable<Integer,Integer> TranTable,
										Hashtable<Integer,Integer> ProcessTable){
		
		//find the lock that this operation needs and try to get from lock_table
		LockTuple LT = new LockTuple();
//		LT.transactionID=cmd.getTransactionId();
		LT.file_name=cmd.getFilename();
		LT.operationType=cmd.getType();

		LockContent LC=null;//=new LockContent();
		if(cmd.isReadCommand()) {
			LT.record_ID=cmd.getId();
			LC=lock_table.get(LT);
//			System.out.println("find lock: is read "+LC);
		} else if(cmd.isWriteCommand()) {
			LT.record_ID=cmd.getDataItem().getId();
			LC=lock_table.get(LT);
//			System.out.println("find lock: is write "+LC);
		}
		System.out.println("LT.file_name:"+LT.file_name+" recordID:"+LT.record_ID+" lock_table size="+lock_table.size()+
				" file_lock_table size="+file_lock_table.size());
//		print_lock_table(lock_table);
//		print_lock_table_key(lock_table);
		LockContent LC_file=file_lock_table.get(cmd.getFilename());
		
		//check whether the process can execute.
		//but a process never get a lock or put in lock table 
		//a process can be in waiting list.
		System.out.println("cmd.getTransactionId()="+cmd.getTransactionId());
		if(ProcessTable.get(cmd.getTransactionId())!=null){
			if(LC!=null){
				if(LC.lock_holder!=null){
					for(int i=0; i<LC.lock_holder.size();i++){
						int row=IdentifyCmdType(cmd,TranTable,ProcessTable);
						int col=IdentifyOptType(LC.lock_holder.get(i),TranTable,ProcessTable);
		//					System.out.println("ComTable.CompatibleTable[row][col]="+ComTable.CompatibleTable[row][col]);
						if(ComTable.CompatibleTable[row][col]==0){
							if(from_release==false){//&&conflicting_flag==false){
								System.out.println("Can't acquire need to insert");
								insert_lock_table_waiter(LC,cmd);
								update_waiting_in_lock_holder_waiting_list(cmd,lock_table,lock_holder_waitting_list,LT);
								
		//						WFGInsertEdge(WFG,cmd,LC);//insert edge to Wait-for-Graph
		//						conflicting_flag=true;
							}
		//						if(from_release==false)
								WFGInsertEdge(WFG,cmd,LC);//insert edge to Wait-for-Graph
							System.out.println("Can't acquire lock");
							return false;
						}
					}
				}
			}
			if(LC_file!=null){
				if(LC_file.lock_holder!=null){
					for(int i=0; i<LC_file.lock_holder.size();i++){
						if(LC_file.lock_holder.get(i).tranID==cmd.getTransactionId()){
							break;
						}
						
						int row=IdentifyCmdType(cmd,TranTable,ProcessTable);
						int col=IdentifyOptType(LC_file.lock_holder.get(i),TranTable,ProcessTable);
		//					System.out.println("ComTable.CompatibleTable[row][col]="+ComTable.CompatibleTable[row][col]);
						if(ComTable.CompatibleTable[row][col]==0){
							if(from_release==false){//&&conflicting_flag==false){
								System.out.println("Can't acquire need to insert");
								insert_lock_table_waiter(LC_file,cmd);
								update_waiting_in_lock_holder_waiting_list(cmd,lock_table,lock_holder_waitting_list,LT);
								
		//						WFGInsertEdge(WFG,cmd,LC);//insert edge to Wait-for-Graph
		//						conflicting_flag=true;
							}
		//						if(from_release==false)
								WFGInsertEdge(WFG,cmd,LC);//insert edge to Wait-for-Graph
							System.out.println("Can't acquire lock");
							return false;
						}
					}
				}
			}
			return true;
		}
	
		if((LC!=null)||(LC_file!=null)) {
			boolean flag=false;
			if(LC==null){
				if(LC_file.lock_holder==null){
					flag=true;
				}
			}
			if(LC_file==null){
				if(LC.lock_holder==null){
					flag=true;
				}	
			}
			if(flag){
				//insert into lock_Table
				if(cmd.isDeleteCommand()||cmd.isMatchCommand()){
					insert_lock_table_holder(LC_file,cmd);
				}else{
					insert_lock_table_holder(LC,cmd);
					if(!(cmd.isDeleteCommand()||cmd.isMatchCommand()))
						update_grant_in_lock_holder_waiting_list(cmd,lock_table,lock_holder_waitting_list,LT);
				}
				
				//delete all out-going edge of the transaction that acquire lock from Wait-for-Graph
				WFGDeleteEdge(WFG,cmd);
				return true;
			} else {
				//check the compatibility of current lock holders to current transaction lock requested
				//if the transaction of the cmd is holding the lock, return true immediately
				//(same transaction)
				if(LC!=null){
					if(LC.lock_holder!=null){
						for(int i=0; i<LC.lock_holder.size();i++){
							if(LC.lock_holder.get(i).tranID==cmd.getTransactionId()&&
									(LC.lock_holder.get(i).operation==cmd.getType()||
									LC.lock_holder.get(i).operation==MyCommand.WRITE)){
								//no need to update lock_table holder
								//no need to update lock_holder_waitting_list?
								//that's because the same lock already held in the lock table
								System.out.println("pass 1");
						//		insert_lock_table_holder(LC,cmd);
						//		update_grant_in_lock_holder_waiting_list(cmd,lock_table,lock_holder_waitting_list,LT);
								
								//delete all out-going edge of the transaction that acquire lock from Wait-for-Graph
								WFGDeleteEdge(WFG,cmd);
								return true;
							}
						}
					}
				}
				
				if(LC_file!=null){
					if(LC_file.lock_holder!=null){
						//check whether the transaction has the lock already in file_lock_table
						for(int i=0;i<LC_file.lock_holder.size();i++){
							if(LC_file.lock_holder.get(i).tranID==cmd.getTransactionId()){
								System.out.println("pass 1.1");
								
								//delete all out-going edge of the transaction that acquire lock from Wait-for-Graph
								WFGDeleteEdge(WFG,cmd);
								return true;
							}
						}
						
						//check any incompatible lock in file_lock_table
						for(int i=0;i<LC_file.lock_holder.size();i++){
							if(LC_file.lock_holder.get(i).tranID!=cmd.getTransactionId()){
								int row=IdentifyCmdType(cmd,TranTable,ProcessTable);
//								int col=LC_file.lock_holder.get(i).operation;
								int col=IdentifyOptType(LC_file.lock_holder.get(i),TranTable,ProcessTable);
								if(ComTable.CompatibleTable[row][col]==0){//0= not compatible
									//may be.....
									insert_lock_table_waiter(LC_file,cmd);
									//update wait for graph
									WFGInsertEdge(WFG,cmd,LC_file);//insert edge to Wait-for-Graph
									return false;
								}
							}
						}
					}
				}
				
				if(LC!=null){
					if(LC.lock_holder!=null){
						//if all lock holder is the same transaction as the cmd transaction, grant lock in lock_table
						int count=0;
						boolean write_lock_appear_flag=false;
						for(int i=0; i<LC.lock_holder.size();i++){
							if(LC.lock_holder.get(i).tranID==cmd.getTransactionId()){
								count++;
								if(LC.lock_holder.get(i).operation==MyCommand.WRITE)
									write_lock_appear_flag=true;
							}
						}
						
						if(count==LC.lock_holder.size()){
							System.out.println("pass 2 count="+count);
							if(write_lock_appear_flag==false){
								insert_lock_table_holder(LC,cmd);
								update_grant_in_lock_holder_waiting_list(cmd,lock_table,lock_holder_waitting_list,LT);
							}
							
							//delete all out-going edge of the transaction that acquire lock from Wait-for-Graph
							WFGDeleteEdge(WFG,cmd);
							return true;
						}
						
						//check any conflicting lock holder(different transaction)
//						boolean conflicting_flag=false;
						for(int i=0; i<LC.lock_holder.size();i++){
							int row=IdentifyCmdType(cmd,TranTable,ProcessTable);
//							int col=LC.lock_holder.get(i).operation;
							int col=IdentifyOptType(LC.lock_holder.get(i),TranTable,ProcessTable);
		//					System.out.println("ComTable.CompatibleTable[row][col]="+ComTable.CompatibleTable[row][col]);
							if(ComTable.CompatibleTable[row][col]==0){
								if(from_release==false){//&&conflicting_flag==false){
									System.out.println("Can't acquire need to insert");
									insert_lock_table_waiter(LC,cmd);
									update_waiting_in_lock_holder_waiting_list(cmd,lock_table,lock_holder_waitting_list,LT);
									
									WFGInsertEdge(WFG,cmd,LC);//insert edge to Wait-for-Graph
//									conflicting_flag=true;
								}
		//						if(from_release==false)
			//						WFGInsertEdge(WFG,cmd,LC);//insert edge to Wait-for-Graph
								WFGInsertEdge(WFG,cmd,LC);//insert edge to Wait-for-Graph
								System.out.println("Can't acquire lock");
								return false;
							}
						}
					}
				}
//				if(conflicting_flag==true)
	//				return false;
				
				System.out.println("pass 3");
				if(cmd.isDeleteCommand()||cmd.isMatchCommand()){
					//reach here means no conflicting lock holder
					insert_lock_table_holder(LC_file,cmd);
				} else {
					//reach here means no conflicting lock holder
					if(LC==null){
						LC=new LockContent();
						lock_table.put(LT, LC);
					}
						
					insert_lock_table_holder(LC,cmd);
					update_grant_in_lock_holder_waiting_list(cmd,lock_table,lock_holder_waitting_list,LT);
				}
				System.out.println("LT.file_name:"+LT.file_name+" recordID:"+LT.record_ID+" lock_table size="+lock_table.size()+
						" file_lock_table size="+file_lock_table.size());
				//delete all out-going edge of the transaction that acquire lock from Wait-for-Graph
				WFGDeleteEdge(WFG,cmd);
				return true;
			}
		} else {//LC==null means no such entry
			System.out.println("pass 4");
			
/*			if(cmd.isDeleteCommand()||cmd.isMatchCommand()){
				//reach here means no conflicting lock holder
				insert_lock_table_holder(LC_file,cmd);
			} else {
				//reach here means no conflicting lock holder
				insert_lock_table_holder(LC,cmd);
				update_grant_in_lock_holder_waiting_list(cmd,lock_table,lock_holder_waitting_list,LT);
			}*/
			
			LockContent LCNew=new LockContent();
			insert_lock_table_holder(LCNew,cmd);
			
			if(cmd.isDeleteCommand()||cmd.isMatchCommand())
				file_lock_table.put(cmd.getFilename(),LCNew);
			else{
				lock_table.put(LT, LCNew);
				update_grant_in_lock_holder_waiting_list(cmd,lock_table,lock_holder_waitting_list,LT);
			}
			//delete all out-going edge of the transaction that acquire lock from Wait-for-Graph
			WFGDeleteEdge(WFG,cmd);
			return true;
		}
	}

	public boolean AcquireLock(MyCommand cmd,Hashtable<LockTuple,LockContent> lock_table,
									Hashtable<Integer, LockGranted> lock_holder_waitting_list,
									CompatibleTable ComTable,boolean from_release,
									DefaultDirectedGraph<Integer, DefaultEdge> WFG, DeadLockManager DLM,
									Hashtable<String,LockContent> file_lock_table,Hashtable<Integer,Integer> TranTable,
									Hashtable<Integer,Integer> ProcessTable){
		boolean result=false;
		
//		if(cmd.isMatchCommand()||cmd.isDeleteCommand()){
//			result=check_file_lock_table(cmd,lock_table,lock_holder_waitting_list,ComTable,from_release,WFG,DLM,file_lock_table);
//		}else{
			//check lock table to see whether we can acquire the lock
			result=check_lock_table(cmd,lock_table,lock_holder_waitting_list,ComTable,from_release,WFG,DLM,file_lock_table,
									TranTable,ProcessTable);
//		}
		
		return result;
	}
	
	public boolean check_all_prior_operation_finish(MyCommand cmd,Hashtable<LockTuple,LockContent> lock_table,
												Hashtable<Integer, LockGranted> lock_holder_waitting_list,
												CompatibleTable ComTable, Hashtable<String,LockContent> file_lock_table){
		
		
		System.out.println("file_lock_table size="+file_lock_table.size());
/*		LockContent LC_file=file_lock_table.get(cmd.getFilename());
		if(LC_file!=null){
			if(LC_file.waiting_list!=null){
				if(LC_file.waiting_list.size()!=0)
					return false;
			}
		}*/
		for(Enumeration<LockContent> e=file_lock_table.elements();e.hasMoreElements();){
			LockContent file_LC= e.nextElement();
			if(file_LC!=null){
				if(file_LC.waiting_list!=null){
					System.out.println("file_LC.waiting_list.size()="+file_LC.waiting_list.size());
					for(int i=0;i<file_LC.waiting_list.size();i++){
						if(file_LC.waiting_list.get(i).getTransactionId()==cmd.getTransactionId()){
							System.out.println("still waiting for a lock in file_lock_table");
							return false;
						}
					}
				}
			}
		}
		
		LockGranted LG=lock_holder_waitting_list.get(cmd.getTransactionId());
		if(LG!=null){
			if(LG._lock_waiting!=null){
				System.out.println("Tran."+cmd.getTransactionId()+" is still waiting for "+LG._lock_waiting.size());
				if(LG._lock_waiting.size()==0)
					return true;
			}else
				return true;
			System.out.println("Tran."+cmd.getTransactionId()+" is still waiting for "+LG._lock_waiting.size()+ " locks. cannot commit!");
		}
		if((LG==null)){//||(LG._lock_waiting!=null)){
//			System.out.println("HERE!!!!!!!!!!!!!!!");
			return true;
		}
			
		return false;
	}
	
	public void remove_waiting_from_lock_holder_waitting_list(MyCommand cmd,Hashtable<Integer, 
																LockGranted> lock_holder_waitting_list){
		ArrayList<LockTuple> w=lock_holder_waitting_list.get(cmd.getTransactionId())._lock_waiting;
		int size=w.size();
		for(int i=0;i<size;i++){
			if(w.get(i).file_name.equals(cmd.getFilename())&&(w.get(i).operationType==cmd.getType())){
				if(cmd.getType()==MyCommand.READ){
					if(w.get(i).record_ID==cmd.getId()){
						System.out.println("removed a waiter from lock_holder_waitting_list");
						System.out.println(cmd.getFilename()+" "+cmd.getId()+" "+cmd.getType());
						w.remove(i);
						i--; size--;
					}
				} else if(cmd.getType()==MyCommand.WRITE){
					if(w.get(i).record_ID==cmd.getDataItem().getId()){
						System.out.println("removed a waiter from lock_holder_waitting_list");
						System.out.println(cmd.getFilename()+" "+cmd.getId()+" "+cmd.getType());
						w.remove(i);
						i--; size--;
					}
				}
			}
		}
	}
	
	public ArrayList<MyCommand> ReleaseLock(MyCommand cmd,Hashtable<LockTuple,LockContent> lock_table,
			Hashtable<Integer, LockGranted> lock_holder_waitting_list,CompatibleTable ComTable,DefaultDirectedGraph<Integer, 
			DefaultEdge> WFG, DeadLockManager DLM, boolean isAbort,Hashtable<String,LockContent> file_lock_table,
			Hashtable<Integer,Integer> TranTable,Hashtable<Integer,Integer> ProcessTable){
		
		ArrayList<MyCommand> execute_list=new ArrayList<MyCommand>();

		//find out which lock is held by the commit transaction
		LockGranted LG=lock_holder_waitting_list.get(cmd.getTransactionId());

//		System.out.println("LG size="+LG._lock_granted.size());
		if(LG!=null){
			//for each held lock, remove it from both lock_table and lock_holder_waitting_list
			if(LG._lock_granted!=null){
				for(int i=0; i<LG._lock_granted.size();i++){
					LockTuple LT=LG._lock_granted.get(i);
					System.out.println("LT "+LT.file_name+" "+LT.record_ID + " lock Type "+LT.operationType);
					LockContent LC= lock_table.get(LT);
					System.out.println("lock_table.size()="+lock_table.size());
					
					//remove the lock from lock_table
					if(LC.lock_holder==null)
						System.out.println("ReleaseLock: LC.lock_holder NULL");
					
					int size=LC.lock_holder.size();
					System.out.println("******************LC.lock_holder.size()="+LC.lock_holder.size());
			//		System.out.println("******************LC.lock_holder="+LC.lock_holder);
					for(int j=0; j<size; j++){
						if(LC.lock_holder.get(j).tranID==cmd.getTransactionId()){
							//remove the lock from lock_holder
							LC.lock_holder.remove(j);
		//					LC.lock_holder.remove(j);
			//				LC.lock_holder_type.remove(j);
							j--; size--;
							
							if(LC.waiting_list!=null){
								System.out.println("-------------- LC.waiting_list.size()="+LC.waiting_list.size());
								int size2=LC.waiting_list.size();
								for(int k=0;k<size2;k++){
									MyCommand waiting_cmd=LC.waiting_list.get(k);
									System.out.println("////k="+k+ "///////"+waiting_cmd.getFilename()
											+" "+waiting_cmd.getId()+" "+waiting_cmd.getType()
											+" "+waiting_cmd.getTimeStamp());
									if(AcquireLock(waiting_cmd,lock_table,lock_holder_waitting_list,ComTable,true,WFG
											,DLM,file_lock_table,TranTable,ProcessTable)==true){
										System.out.println("Acquire lock success!");
										LC.waiting_list.remove(k);
										remove_waiting_from_lock_holder_waitting_list(waiting_cmd,lock_holder_waitting_list);
										execute_list.add(waiting_cmd);
										k--; size2--;
	//									break;
									}
	//								k--; size2--;
								}
								System.out.println("-------------- execute_list.size()="+execute_list.size());
								System.out.println("-------------- LC.waiting_list.size()="+LC.waiting_list.size());
								System.out.println("******************LC.lock_holder.size()="+LC.lock_holder.size());
							}
						}
					}
				}
			}
		}
///////////////////////////////////////////////////////////////////////////////////////////////////////
		System.out.println("Check the file_lock_table");
		for(Enumeration<LockContent> e=file_lock_table.elements();e.hasMoreElements();){
			LockContent file_LC= e.nextElement();
			int size=file_LC.lock_holder.size();
			System.out.println("file_LC.lock_holder.size()="+size);
			for(int i=0;i<size;i++){
				//release lock
				if(file_LC.lock_holder.get(i).tranID==cmd.getTransactionId()){
					file_LC.lock_holder.remove(i);
					System.out.println("a lock in file_lock_table released file_LC.lock_holder.size()="+file_LC.lock_holder.size());
					i--; size--;
					
					if(file_LC.waiting_list!=null){
						System.out.println("-------------- file_LC.waiting_list.size()="+file_LC.waiting_list.size());
						int size2=file_LC.waiting_list.size();
						for(int k=0;k<size2;k++){
							MyCommand waiting_cmd=file_LC.waiting_list.get(k);
							System.out.println("////k="+k+ "///////"+waiting_cmd.getFilename()
									+" "+waiting_cmd.getId()+" "+waiting_cmd.getType()
									+" "+waiting_cmd.getTimeStamp());
							if(AcquireLock(waiting_cmd,lock_table,lock_holder_waitting_list,ComTable,true,WFG,DLM,
									file_lock_table,TranTable,ProcessTable)==true){
								System.out.println("Acquire lock success!");
								file_LC.waiting_list.remove(k);
								//remove_waiting_from_lock_holder_waitting_list(waiting_cmd,lock_holder_waitting_list);
								execute_list.add(waiting_cmd);
								k--; size2--;
							}
						}
					}
				}
			}
		}
		
///////////////////////////////////////////////////////////////////////////////////////////////////////
		
///////////////////////////////for abort only//////////////////////////////////////////////////////////
		if(isAbort==true){//if it is abort, remove all waiting of the abort transaction
			System.out.print("Start to clean up waiter of aborted tran in lock_table");
//			for(int i=0; i<lock_table.size();i++){
			for(Enumeration<LockContent> e=lock_table.elements();e.hasMoreElements();){
				LockContent LC= e.nextElement();
				if(LC.waiting_list!=null){
					int size=LC.waiting_list.size();
					for(int j=0;j<size;j++){
						if(cmd.getTransactionId()==LC.waiting_list.get(j).getTransactionId()){
							LC.waiting_list.remove(j);
							j--; size--;
						}
							
					}
				}
			}
			
/*			for(int i=0; i<LG._lock_waiting.size();i++){
//				System.out.println("cmd tranID="+cmd.getTransactionId()+" waiting tranID "+waiting_cmd.getTransactionId());
				LockTuple LT=LG._lock_granted.get(i);
				LockContent LC= lock_table.get(LT);
				int size=LC.waiting_list.size();
				for(int j=0; j<size; j++){
					if(cmd.getTransactionId()==LC.waiting_list.get(j).getTransactionId()){
	//						cmd.getFilename().equals(waiting_cmd.getFilename())
	//										&&cmd.getId()==waiting_cmd.getId()){
						System.out.println("isAbort "+cmd.getTransactionId()+" "+LC.waiting_list.get(j).getTransactionId());
						LC.waiting_list.remove(j);
	//					remove_waiting_from_lock_holder_waitting_list(waiting_cmd,lock_holder_waitting_list);
						j--; size--;
					}
				}
			}*/
		}
		//remove the lock from lock_holder_waitting_list
		LG=null;//check not sure!
		
		return execute_list;
	}
}
